#include <jni.h>
#include <string>

#include <iostream>
#include "AES.h"
#include "Base64.h"

extern "C"
string EncryptionAES(const string &strSrc);

string DecryptionAES(const string &strSrc);


using namespace std;

const char g_key[17] = "db0bf515044b1bf3";
const char g_iv[17] = "";

extern "C"
JNIEXPORT jstring

JNICALL
Java_com_dj17_client_api_ApiManager_encrypt(
        JNIEnv *env,
        jobject /* this */
,jstring passWord) {
    const char* str = env->GetStringUTFChars(passWord, 0);

    cout << "加密前:" << passWord << endl;
    string str2 = EncryptionAES(str);
    cout << "加密后:" << str2 << endl;
    string str3 = DecryptionAES(str2);
    cout << "解密后:" << str3 << endl;

    return env->NewStringUTF(str2.c_str());
}


//string EncryptionAES(const string& strSrc) //AES加密
string EncryptionAES(const string &strSrc) //AES加密
{
    size_t length = strSrc.length();
    int block_num = length / BLOCK_SIZE + 1;
    //明文
    char *szDataIn = new char[block_num * BLOCK_SIZE + 1];
    memset(szDataIn, 0x00, block_num * BLOCK_SIZE + 1);
    strcpy(szDataIn, strSrc.c_str());

    //进行PKCS7Padding填充。
    int k = length % BLOCK_SIZE;
    int j = length / BLOCK_SIZE;
    int padding = BLOCK_SIZE - k;
    for (int i = 0; i < padding; i++) {
        szDataIn[j * BLOCK_SIZE + k + i] = padding;
    }
    szDataIn[block_num * BLOCK_SIZE] = '\0';

    //加密后的密文
    char *szDataOut = new char[block_num * BLOCK_SIZE + 1];
    memset(szDataOut, 0, block_num * BLOCK_SIZE + 1);

    //进行进行AES的ecb模式加密
    AES aes;
    aes.MakeKey(g_key, g_iv, 16, 16);
    aes.Encrypt(szDataIn, szDataOut, block_num * BLOCK_SIZE, AES::ECB);
    string str = base64_encode((unsigned char *) szDataOut,
                               block_num * BLOCK_SIZE);
    delete[] szDataIn;
    delete[] szDataOut;
    return str;
}

string DecryptionAES(const string &strSrc) //AES解密
{
    string strData = base64_decode(strSrc);
    size_t length = strData.length();
    //密文
    char *szDataIn = new char[length + 1];
    memcpy(szDataIn, strData.c_str(), length + 1);
    //明文
    char *szDataOut = new char[length + 1];
    memcpy(szDataOut, strData.c_str(), length + 1);

    //进行AES的CBC模式解密
    AES aes;
    aes.MakeKey(g_key, g_iv, 16, 16);
    aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);

    //去PKCS7Padding填充
    if (0x00 < szDataOut[length - 1] <= 0x16) {
        int tmp = szDataOut[length - 1];
        for (int i = length - 1; i >= length - tmp; i--) {
            if (szDataOut[i] != tmp) {
                memset(szDataOut, 0, length);
                cout << "去填充失败！解密出错！！" << endl;
                break;
            } else
                szDataOut[i] = 0;
        }
    }
    string strDest(szDataOut);
    delete[] szDataIn;
    delete[] szDataOut;
    return strDest;


}